﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Citi.Import.Util;
using Citi.ResourceConsolidation.Domain.Utils;

namespace Citi.ResourceConsolidation.Domain
{
    public partial class JobTitle
    {
        private static readonly List<JobTitle> JobTitleCache = new JobTitle().SelectAll<JobTitle>();
        private static readonly List<JobFamily> JobFamilyCache = new JobFamily().SelectAll<JobFamily>();
        
        private const string JobTitleColumn = "Job Title";
        private const string JobCodeColumn = "Job Code";
        private const string JobFamilyColumn = "Job Family";

        public static readonly List<Definition<JobTitle>> Definitions = new List<Definition<JobTitle>>
            {
                new Definition<JobTitle> { ModelProperty = x => x.Code, MaxLength = 10, Required = true, ColumnName = JobCodeColumn, CustomConversionMethod = ValidateCode},
                new Definition<JobTitle> { ModelProperty = x => x.Description, MaxLength = 200, Required = true, ColumnName = JobTitleColumn},
                new Definition<JobTitle> { ModelProperty = x => x.JobFamily, Required = true, ColumnName = JobFamilyColumn, CustomConversionMethod = ValidateFamily }
            };

        private static object ValidateCode(ref JobTitle model, string value, List<string> fields, ref string error, List<string> headers = null)
        {
            if (string.IsNullOrEmpty(value))
            {
                error = string.Format("The field {0} can not be null", JobTitleColumn);
                return Conversion.Validation.Failed;
            }

            var domain = CacheFacade.Get(new JobTitle().SelectAll<JobTitle>).FirstOrDefault(x => x.Code == value);

            if (domain != null)
            {
                model = domain;
                return Conversion.Validation.Validated;
            }

            return value;
        }

        private static object ValidateFamily(ref JobTitle model, string value, List<string> fields, ref string error, List<string> headers = null)
        {
            if (string.IsNullOrEmpty(value))
            {
                error = string.Format("The field {0} can not be null", JobFamilyColumn);
                return Conversion.Validation.Failed;
            }

            //var domain = JobFamilyCache.FirstOrDefault(x => x.Description == value);
            var domain = CacheFacade.Get(new JobFamily().SelectAll<JobFamily>).FirstOrDefault(x => x.Description == value);

            if (domain != null)
            {
                model.JobFamily = domain;
                return Conversion.Validation.Validated;
            }

            return value;
        }

        public static void Save(List<JobTitle> titles)
        {
            titles = titles.Distinct(new JobTitleComparer()).Where(x => x != null && x.Id == 0).ToList();

            if (!titles.Any()) return;
            titles.First().Save(titles, 100);

            CacheFacade.Clear(typeof(JobTitle));
            CacheFacade.Clear(typeof(JobFamily));
            Context.ClearContext();
        }
    }

    public class JobTitleComparer : IEqualityComparer<JobTitle>
    {
        public bool Equals(JobTitle x, JobTitle y)
        {
            if (ReferenceEquals(x, y)) return true;
            if (ReferenceEquals(x, null) || ReferenceEquals(y, null))
                return false;

            return x.Description == y.Description && x.Id == y.Id && x.Code == y.Code && x.JobFamilyId == y.JobFamilyId;
        }

        public int GetHashCode(JobTitle item)
        {
            if (ReferenceEquals(item, null)) return 0;

            int hashDescription = item.Description == null ? 0 : item.Description.GetHashCode();
            int hashId = item.Description == null ? 0 : item.Id.GetHashCode();

            return hashDescription ^ hashId;
        }
    }
}
